from fastapi import APIRouter, Depends, HTTPException
from fastapi import Body
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
from app.db.postgres import get_session
from app.models import Activity
from app.schemas.activity import ActivityCreate, ActivityRead, ActivityUpdate
from datetime import datetime, timezone


router = APIRouter(prefix="/activities", tags=["activities"]) 


@router.get("")
async def list_activities(
    name: str | None = None,
    activity_type_id: str | None = None,
    location_admin: str | None = None,
    status: str | None = None,
    time_start: str | None = None,
    time_end: str | None = None,
    page: int = 1,
    page_size: int = 10,
    session: AsyncSession = Depends(get_session),
):
    stmt = select(Activity)
    count_stmt = select(func.count()).select_from(Activity)
    conds = []
    if name:
        like = f"%{name}%"
        conds.append(Activity.name.ilike(like))
    if activity_type_id:
        try:
            from uuid import UUID
            _uuid = UUID(activity_type_id)
            conds.append(Activity.activity_type_id == _uuid)
        except Exception:
            pass
    if location_admin:
        conds.append(Activity.location_admin.ilike(f"%{location_admin}%"))
    if status:
        conds.append(Activity.status == status)
    if time_start:
        try:
            ts = datetime.strptime(time_start, "%Y-%m-%d")
            conds.append((Activity.time_start == None) | (Activity.time_start >= ts))
        except Exception:
            try:
                ts = datetime.fromisoformat(time_start)
                conds.append((Activity.time_start == None) | (Activity.time_start >= ts))
            except Exception:
                pass
    if time_end:
        try:
            te = datetime.strptime(time_end, "%Y-%m-%d")
            conds.append((Activity.time_end == None) | (Activity.time_end <= te))
        except Exception:
            try:
                te = datetime.fromisoformat(time_end)
                conds.append((Activity.time_end == None) | (Activity.time_end <= te))
            except Exception:
                pass
    if conds:
        from sqlalchemy import and_
        stmt = stmt.where(and_(*conds))
        count_stmt = count_stmt.where(and_(*conds))
    total_res = await session.execute(count_stmt)
    total = total_res.scalar() or 0
    res = await session.execute(
        stmt.order_by(Activity.created_at.desc()).offset((page - 1) * page_size).limit(page_size)
    )
    items = [ActivityRead.model_validate(x) for x in res.scalars().all()]
    return {"items": items, "total": total}


@router.post("", response_model=ActivityRead)
async def create_activity(payload: ActivityCreate, session: AsyncSession = Depends(get_session)):
    data = payload.model_dump()
    for key in ("time_start", "time_end", "approved_at"):
        v = data.get(key)
        if isinstance(v, str) and v:
            try:
                data[key] = datetime.strptime(v, "%Y-%m-%d")
            except Exception:
                # 尝试更通用的解析
                try:
                    data[key] = datetime.fromisoformat(v)
                except Exception:
                    data[key] = None
    # 将可选字段的空字符串归一化为 None，避免枚举/时间列入库失败
    optional_empty_to_null = {
        "organizer", "location_detail", "contact_name", "contact_phone", "approver_name",
        "approval_result", "attachments_ref_id"
    }
    for k in optional_empty_to_null:
        v = data.get(k)
        if isinstance(v, str) and v.strip() == "":
            data[k] = None
    obj = Activity(**data)
    session.add(obj)
    await session.flush()
    await session.refresh(obj)
    await session.commit()
    return ActivityRead.model_validate(obj)


@router.get("/{activity_id}", response_model=ActivityRead)
async def get_activity(activity_id: str, session: AsyncSession = Depends(get_session)):
    obj = await session.get(Activity, activity_id)
    if not obj:
        raise HTTPException(status_code=404, detail="活动不存在")
    return ActivityRead.model_validate(obj)


@router.put("/{activity_id}", response_model=ActivityRead)
async def update_activity(activity_id: str, payload: ActivityUpdate, session: AsyncSession = Depends(get_session)):
    obj = await session.get(Activity, activity_id)
    if not obj:
        raise HTTPException(status_code=404, detail="活动不存在")
    data = payload.model_dump(exclude_unset=True)
    for key in ("time_start", "time_end", "approved_at"):
        v = data.get(key)
        if isinstance(v, str) and v:
            try:
                data[key] = datetime.strptime(v, "%Y-%m-%d")
            except Exception:
                try:
                    data[key] = datetime.fromisoformat(v)
                except Exception:
                    data[key] = None
    optional_empty_to_null = {
        "organizer", "location_detail", "contact_name", "contact_phone", "approver_name",
        "approval_result", "attachments_ref_id"
    }
    for k in optional_empty_to_null:
        v = data.get(k)
        if isinstance(v, str) and v.strip() == "":
            data[k] = None
    for k, v in data.items():
        setattr(obj, k, v)
    obj.updated_at = datetime.now(timezone.utc)
    await session.flush()
    await session.refresh(obj)
    await session.commit()
    return ActivityRead.model_validate(obj)


@router.patch("/{activity_id}/indicator-version")
async def set_activity_indicator_version(activity_id: str, payload: dict = Body(...), session: AsyncSession = Depends(get_session)):
    obj = await session.get(Activity, activity_id)
    if not obj:
        raise HTTPException(status_code=404, detail="活动不存在")
    indicator_version_id = payload.get("indicator_version_id")
    obj.indicator_version_id = indicator_version_id
    obj.updated_at = datetime.now(timezone.utc)
    await session.flush()
    await session.refresh(obj)
    await session.commit()
    return {"ok": True}


@router.delete("/{activity_id}")
async def delete_activity(activity_id: str, session: AsyncSession = Depends(get_session)):
    obj = await session.get(Activity, activity_id)
    if not obj:
        raise HTTPException(status_code=404, detail="活动不存在")
    await session.delete(obj)
    await session.commit()
    return {"ok": True}
